www.gusucode.com > VC++ 编写软件自动升级服务源代码 > VC++ 编写软件自动升级服务源代码/gusucode/updater_src0.8.1.6/Download.cpp
/******************************************************************** created: 2005/03/02 created: 2:3:2005 10:55 filename: Download.cpp file path: Updater file base: Download file ext: cpp author: Geert van Horrik purpose: *********************************************************************/ //********************************************************************* // INCLUDES //********************************************************************* #include "stdafx.h" #include "Updater.h" #include "Download.h" //********************************************************************* // MESSAGE MAP //********************************************************************* BEGIN_MESSAGE_MAP(CDownload, CWinThread) ON_THREAD_MESSAGE(WMU_SETPARENT, OnSetParent) ON_THREAD_MESSAGE(WMU_THREADMESSAGE, OnThreadMessage) ON_THREAD_MESSAGE(WMU_DOWNLOAD_STATUS, OnDownloadStatus) ON_THREAD_MESSAGE(WMU_DOWNLOAD_COMPLETE, OnDownloadComplete) ON_THREAD_MESSAGE(WMU_ERROR, OnError) END_MESSAGE_MAP() //********************************************************************* // CONSTRUCTOR & DESTRUCTOR //********************************************************************* IMPLEMENT_DYNCREATE(CDownload, CWinThread) //===================================================================== CDownload::CDownload() { } //===================================================================== CDownload::~CDownload() { } //********************************************************************* // PUBLIC FUNCTIONS //********************************************************************* BOOL CDownload::InitInstance() { // Log CLog::Instance()->Log(_T("CDownload::InitInstance")); // Set parent to NULL m_pParent = NULL; // We are not started yet m_bStarted = false; // Init singleton classes m_pFunctions = CFunctions::Instance(); m_pSettings = CSettings::Instance(); m_pUpdateInfo = CUpdateInfo::Instance(); m_pInternet = CInternet::Instance(); m_pPath = CPath::Instance(); // Set parent for internet m_pInternet->SetParent(this); // Reserve memory for buffer m_szFilename = (TCHAR *)malloc(sizeof(TCHAR) * 500); ZeroMemory(m_szFilename, sizeof(TCHAR) * 500); return TRUE; } //===================================================================== int CDownload::ExitInstance() { // Log CLog::Instance()->Log(_T("CDownload::ExitInstance")); // Stop all download processes that "might" be running m_pInternet->StopDownloading(); // Auto clean-up thread m_bAutoDelete = TRUE; // Call original function return CWinThread::ExitInstance(); } //********************************************************************* // PRIVATE FUNCTIONS //********************************************************************* void CDownload::Main() { // Initialise the downloads if (!InitDownloads()) { // Send error message PostMessageToParent(WMU_ERROR, ERROR_FILENOTFOUND, (LPARAM)m_szFilename); PostThreadMessage(WM_QUIT, 0, 0); return; } // Check if we have enough diskspace if (!EnoughFreeDiskSpace()) { PostMessageToParent(WMU_ERROR, ERROR_NODISKSPACE, m_iTotalBytes); PostThreadMessage(WM_QUIT, 0, 0); return; } // If we have any downloads if (m_iDownloadCount > 0) { // Start first download StartDownload(0); } else { // Put empty string into char buffer lstrcpy(m_szFilename, _T("")); // Set progress to 100% PostMessageToParent(WMU_UPDATE_GUI_FILEPROGRESS, 100, (LPARAM)m_szFilename); PostMessageToParent(WMU_UPDATE_GUI_TOTALPROGRESS, 100, 0); // Send message to parent that we are ready PostMessageToParent(WMU_TASK_COMPLETE, TASK_DOWNLOAD, 0); // Exit the thread PostThreadMessage(WM_QUIT, 0, 0); } } //===================================================================== bool CDownload::InitDownloads() { // Declare variables m_iDownloadCount = 0; m_iTotalBytes = 0; m_iCurrentActionPoints = 0; m_iTotalActionPoints = 0; CFileData * pFileData; CActionDownload * pActionDownload; int iFileSize, k; CString sName; // For all files for (int i = 0; i < m_pUpdateInfo->GetFileCount(); i++) { // Get file object pFileData = m_pUpdateInfo->GetFileData(i); // Should we update file? if (pFileData->GetUpdateFile()) { // For all actions for (int j = 0; j < pFileData->GetActionCount(); j++) { // Check if action is a download if (pFileData->GetAction(j)->GetType() == ACTION_DOWNLOAD) { // Get object pActionDownload = (CActionDownload *)pFileData->GetAction(j); // Put string into char buffer sName = pFileData->GetName(); lstrcpy(m_szFilename, sName); // Init k k = 0; iFileSize = -1; // While we did not found any valid location and we have still locations while ((k < pActionDownload->GetDownloadLocationCount()) && (iFileSize == -1)) { // Can we get filesize? iFileSize = m_pInternet->GetFileSize(pActionDownload->GetDownloadLocation(k)); // Did we get filesize successfully? if (iFileSize != -1) { // Create struct DownloadInfo tmpDownloadInfo; tmpDownloadInfo.sTitle = pFileData->GetName(); tmpDownloadInfo.sFilename = pFileData->GetFilename(); tmpDownloadInfo.sDownloadLocation = pActionDownload->GetDownloadLocation(k); tmpDownloadInfo.sDestination = pActionDownload->GetDownloadDestination(); // Add to array m_arrDownloads[m_iDownloadCount++] = tmpDownloadInfo; // Also add it to the garbage collector if (pActionDownload->SubscribeToGarbageCollector()) { CGarbageCollector::Instance()->AddFileToRemove(tmpDownloadInfo.sDestination); } // Also add filesize to total filesize m_iTotalBytes += iFileSize; // Calculate action points for file m_iTotalActionPoints += CActionPoints::CalculateActionPoints(iFileSize); } else { // No, we failed k++; } } // If filesize is still -1 if (iFileSize == -1) { // File could not be found! return false; } } } } } // If we get here, function is successful return true; } //===================================================================== void CDownload::StartDownload(int iDownload) { // Declare variables CString sDestination, sName; // Set current download m_iCurrentDownload = iDownload; m_iTempActionPoints = 0; // Set up filename on hard-disk sDestination = m_arrDownloads[m_iCurrentDownload].sDestination; // Put string into char buffer sName = m_pPath->ExtractFileName(m_arrDownloads[m_iCurrentDownload].sTitle); lstrcpy(m_szFilename, sName); // Start download if (!m_pInternet->DownloadFile(m_arrDownloads[m_iCurrentDownload].sDownloadLocation, sDestination, m_pUpdateInfo->GetResumeDownloads())) { // Post error PostMessageToParent(WMU_ERROR, ERROR_DOWNLOADFILE, (LPARAM)m_szFilename); } } //===================================================================== void CDownload::StartNextDownload() { // Update current download m_iCurrentDownload++; // Do we still have any downloads? if (m_iCurrentDownload < m_iDownloadCount) { // Start next download StartDownload(m_iCurrentDownload); } else { // Always end up with 100% PostMessageToParent(WMU_UPDATE_GUI_FILEPROGRESS, 100, (LPARAM)m_szFilename); PostMessageToParent(WMU_UPDATE_GUI_TOTALPROGRESS, 100, 0); // Send message to parent that we are ready PostMessageToParent(WMU_TASK_COMPLETE, TASK_DOWNLOAD, 0); // Exit the thread PostThreadMessage(WM_QUIT, 0, 0); } } //===================================================================== bool CDownload::EnoughFreeDiskSpace() { // Declare variables ULARGE_INTEGER liBytesForCaller; ULARGE_INTEGER liBytesCount; ULARGE_INTEGER liFreeBytesCount; // Get data if (!GetDiskFreeSpaceEx(m_pPath->GetPathTemp(), &liBytesForCaller, &liBytesCount, &liFreeBytesCount)) { // We can't check if we have enough disk space return false; } // Check if we have enough if (liFreeBytesCount.QuadPart > m_iTotalBytes) return true; // We do not have enough diskspace return false; } //===================================================================== void CDownload::PostMessageToParent(UINT message, WPARAM wParam, LPARAM lParam) { // Check if parent is still valid if (!IsBadReadPtr(m_pParent, sizeof(CWinThread *))) { // Send message m_pParent->PostThreadMessage(message, wParam, lParam); } } //===================================================================== void CDownload::OnDownloadStatus(WPARAM wParam, LPARAM lParam) { // Declare variables int iFileProgress, iTotalProgress; // Calculate percentage of file progress iFileProgress = (wParam * 100) / lParam; // Calculate percentage of total progress m_iCurrentActionPoints += (wParam - m_iTempActionPoints); m_iTempActionPoints = wParam; if (m_iTotalActionPoints != 0) iTotalProgress = (m_iCurrentActionPoints * 100) / m_iTotalActionPoints; else iTotalProgress = 100; // Update GUI only when needed if (m_iFileProgress != iFileProgress) { PostMessageToParent(WMU_UPDATE_GUI_FILEPROGRESS, iFileProgress, (LPARAM)m_szFilename); } if (m_iTotalProgress != iTotalProgress) { PostMessageToParent(WMU_UPDATE_GUI_TOTALPROGRESS, iTotalProgress, 0); } // Update data m_iTotalProgress = iTotalProgress; m_iFileProgress = iFileProgress; } //===================================================================== void CDownload::OnDownloadComplete(WPARAM wParam, LPARAM lParam) { // Yes, another download completed, start next download StartNextDownload(); } //===================================================================== void CDownload::OnError(WPARAM wParam, LPARAM lParam) { // The download failed! PostMessageToParent(WMU_ERROR, ERROR_DOWNLOADFILE, (LPARAM)m_szFilename); // Exit thread PostThreadMessage(WM_QUIT, 0, 0); } //===================================================================== void CDownload::OnSetParent(WPARAM wParam, LPARAM lParam) { // Set parent m_pParent = (CWinThread *)wParam; } //===================================================================== void CDownload::OnThreadMessage(WPARAM wParam, LPARAM lParam) { // Declare variables int iThreadAction = (int)wParam; // Check what task to perform for thread switch (iThreadAction) { case THREAD_START: // Are we already started? if (!m_bStarted) { // Start main function Main(); } break; case THREAD_PAUSE: // Pause thread SuspendThread(); break; case THREAD_RESUME: // Resume thread ResumeThread(); break; case THREAD_CANCEL: // Exit thread PostThreadMessage(WM_QUIT, 0, 0); break; case THREAD_FINISH: // Exit thread PostThreadMessage(WM_QUIT, 0, 0); break; } }